$attachment = get_post( $id ); /** * Fires after a single attachment is created or updated via the REST API. * * @since 4.7.0 * * @param WP_Post $attachment Inserted or updated attachment object. * @param WP_REST_Request $request The request sent to the API. * @param bool $creating True when creating an attachment, false when updating. */ do_action( 'rest_insert_attachment', $attachment, $request, true ); return array( 'attachment_id' => $id, 'file' => $file, ); } /** * Determines the featured media based on a request param. * * @since 6.5.0 * * @param int $featured_media Featured Media ID. * @param int $post_id Post ID. * @return bool|WP_Error Whether the post thumbnail was successfully deleted, otherwise WP_Error. */ protected function handle_featured_media( $featured_media, $post_id ) { $post_type = get_post_type( $post_id ); $thumbnail_support = current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' ); // Similar check as in wp_insert_post(). if ( ! $thumbnail_support && get_post_mime_type( $post_id ) ) { if ( wp_attachment_is( 'audio', $post_id ) ) { $thumbnail_support = post_type_supports( 'attachment:audio', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:audio' ); } elseif ( wp_attachment_is( 'video', $post_id ) ) { $thumbnail_support = post_type_supports( 'attachment:video', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:video' ); } } if ( $thumbnail_support ) { return parent::handle_featured_media( $featured_media, $post_id ); } return new WP_Error( 'rest_no_featured_media', sprintf( /* translators: %s: attachment mime type */ __( 'This site does not support post thumbnails on attachments with MIME type %s.' ), get_post_mime_type( $post_id ) ), array( 'status' => 400 ) ); } /** * Updates a single attachment. * * @since 4.7.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. */ public function update_item( $request ) { if ( ! empty( $request['post'] ) && in_array( get_post_type( $request['post'] ), array( 'revision', 'attachment' ), true ) ) { return new WP_Error( 'rest_invalid_param', __( 'Invalid parent type.' ), array( 'status' => 400 ) ); } $attachment_before = get_post( $request['id'] ); $response = parent::update_item( $request ); if ( is_wp_error( $response ) ) { return $response; } $response = rest_ensure_response( $response ); $data = $response->get_data(); if ( isset( $request['alt_text'] ) ) { update_post_meta( $data['id'], '_wp_attachment_image_alt', $request['alt_text'] ); } $attachment = get_post( $request['id'] ); if ( ! empty( $schema['properties']['featured_media'] ) && isset( $request['featured_media'] ) ) { $thumbnail_update = $this->handle_featured_media( $request['featured_media'], $attachment->ID ); if ( is_wp_error( $thumbnail_update ) ) { return $thumbnail_update; } } $fields_update = $this->update_additional_fields_for_object( $attachment, $request ); if ( is_wp_error( $fields_update ) ) { return $fields_update; } $request->set_param( 'context', 'edit' ); /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */ do_action( 'rest_after_insert_attachment', $attachment, $request, false ); wp_after_insert_post( $attachment, true, $attachment_before ); $response = $this->prepare_item_for_response( $attachment, $request ); $response = rest_ensure_response( $response ); return $response; } /** * Performs post-processing on an attachment. * * @since 5.3.0 * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. */ public function post_process_item( $request ) { switch ( $request['action'] ) { case 'create-image-subsizes': require_once ABSPATH . 'wp-admin/includes/image.php'; wp_update_image_subsizes( $request['id'] ); break; } $request['context'] = 'edit'; return $this->prepare_item_for_response( get_post( $request['id'] ), $request ); } /** * Checks if a given request can perform post-processing on an attachment. * * @since 5.3.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. */ public function post_process_item_permissions_check( $request ) { return $this->update_item_permissions_check( $request ); } /** * Checks if a given request has access to editing media. * * @since 5.5.0 * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if the request has read access, WP_Error object otherwise. */ public function edit_media_item_permissions_check( $request ) { if ( ! current_user_can( 'upload_files' ) ) { return new WP_Error( 'rest_cannot_edit_image', __( 'Sorry, you are not allowed to upload media on this site.' ), array( 'status' => rest_authorization_required_code() ) ); } return $this->update_item_permissions_check( $request ); } /** * Applies edits to a media item and creates a new attachment record. * * @since 5.5.0 * @since 6.9.0 Adds flips capability and editable fields for the newly-created attachment post. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure. */ public function edit_media_item( $request ) { require_once ABSPATH . 'wp-admin/includes/image.php'; $attachment_id = $request['id']; // This also confirms the attachment is an image. $image_file = wp_get_original_image_path( $attachment_id ); $image_meta = wp_get_attachment_metadata( $attachment_id ); if ( ! $image_meta || ! $image_file || ! wp_image_file_matches_image_meta( $request['src'], $image_meta, $attachment_id ) ) { return new WP_Error( 'rest_unknown_attachment', __( 'Unable to get meta information for file.' ), array( 'status' => 404 ) ); } $supported_types = array( 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif', 'image/heic' ); $mime_type = get_post_mime_type( $attachment_id ); if ( ! in_array( $mime_type, $supported_types, true ) ) { return new WP_Error( 'rest_cannot_edit_file_type', __( 'This type of file cannot be edited.' ), array( 'status' => 400 ) ); } // The `modifiers` param takes precedence over the older format. if ( isset( $request['modifiers'] ) ) { $modifiers = $request['modifiers']; } else { $modifiers = array(); if ( isset( $request['flip']['horizontal'] ) || isset( $request['flip']['vertical'] ) ) { $flip_args = array( 'vertical' => isset( $request['flip']['vertical'] ) ? (bool) $request['flip']['vertical'] : false, 'horizontal' => isset( $request['flip']['horizontal'] ) ? (bool) $request['flip']['horizontal'] : false, ); $modifiers[] = array( 'type' => 'flip', 'args' => array( 'flip' => $flip_args, ), ); } if ( ! empty( $request['rotation'] ) ) { $modifiers[] = array( 'type' => 'rotate', 'args' => array( 'angle' => $request['rotation'], ), ); } if ( isset( $request['x'], $request['y'], $request['width'], $request['height'] ) ) { $modifiers[] = array( 'type' => 'crop', 'args' => array( 'left' => $request['x'], 'top' => $request['y'], 'width' => $request['width'], 'height' => $request['height'], ), ); } if ( 0 === count( $modifiers ) ) { return new WP_Error( 'rest_image_not_edited', __( 'The image was not edited. Edit the image before applying the changes.' ), array( 'status' => 400 ) ); } } /* * If the file doesn't exist, attempt a URL fopen on the src link. * This can occur with certain file replication plugins. * Keep the original file path to get a modified name later. */ $image_file_to_edit = $image_file; if ( ! file_exists( $image_file_to_edit ) ) { $image_file_to_edit = _load_image_to_edit_path( $attachment_id ); } $image_editor = wp_get_image_editor( $image_file_to_edit ); if ( is_wp_error( $image_editor ) ) { return new WP_Error( 'rest_unknown_image_file_type', __( 'Unable to edit this image.' ), array( 'status' => 500 ) ); } foreach ( $modifiers as $modifier ) { $args = $modifier['args']; switch ( $modifier['type'] ) { case 'flip': /* * Flips the current image. * The vertical flip is the first argument (flip along horizontal axis), the horizontal flip is the second argument (flip along vertical axis). * See: WP_Image_Editor::flip() */ $result = $image_editor->flip( $args['flip']['vertical'], $args['flip']['horizontal'] ); if ( is_wp_error( $result ) ) { return new WP_Error( 'rest_image_flip_failed', __( 'Unable to flip this image.' ), array( 'status' => 500 ) ); } break; case 'rotate': // Rotation direction: clockwise vs. counterclockwise. $rotate = 0 - $args['angle']; if ( 0 !== $rotate ) { $result = $image_editor->rotate( $rotate ); if ( is_wp_error( $result ) ) { return new WP_Error( 'rest_image_rotation_failed', __( 'Unable to rotate this image.' ), array( 'status' => 500 ) ); } } break; case 'crop': $size = $image_editor->get_size(); $crop_x = (int) round( ( $size['width'] * $args['left'] ) / 100.0 ); $crop_y = (int) round( ( $size['height'] * $args['top'] ) / 100.0 ); $width = (int) round( ( $size['width'] * $args['width'] ) / 100.0 ); $height = (int) round( ( $size['height'] * $args['height'] ) / 100.0 ); if ( $size['width'] !== $width || $size['height'] !== $height ) { $result = $image_editor->crop( $crop_x, $crop_y, $width, $height ); if ( is_wp_error( $result ) ) { return new WP_Error( 'rest_image_crop_failed', __( 'Unable to crop this image.' ), array( 'status' => 500 ) ); } } break; } } // Calculate the file name. $image_ext = pathinfo( $image_file, PATHINFO_EXTENSION ); $image_name = wp_basename( $image_file, ".{$image_ext}" ); /* * Do not append multiple `-edited` to the file name. * The user may be editing a previously edited image. */ if ( preg_match( '/-edited(-\d+)?$/', $image_name ) ) { // Remove any `-1`, `-2`, etc. `wp_unique_filename()` will add the proper number. $image_name = preg_replace( '/-edited(-\d+)?$/', '-edited', $image_name ); } else { // Append `-edited` before the extension. $image_name .= '-edited'; } $filename = "{$image_name}.{$image_ext}"; // Create the uploads subdirectory if needed. $uploads = wp_upload_dir(); // Make the file name unique in the (new) upload directory. $filename = wp_unique_filename( $uploads['path'], $filename ); // Save to disk. $saved = $image_editor->save( $uploads['path'] . "/$filename" ); if ( is_wp_error( $saved ) ) { return $saved; } // Grab original attachment post so we can use it to set defaults. $original_attachment_post = get_post( $attachment_id ); // Check request fields and assign default values. $new_attachment_post = $this->prepare_item_for_database( $request ); $new_attachment_post->post_mime_type = $saved['mime-type']; $new_attachment_post->guid = $uploads['url'] . "/$filename"; // Unset ID so wp_insert_attachment generates a new ID. unset( $new_attachment_post->ID ); // Set new attachment post title with fallbacks. $new_attachment_post->post_title = $new_attachment_post->post_title ?? $original_attachment_post->post_title ?? $image_name; // Set new attachment post caption (post_excerpt). $new_attachment_post->post_excerpt = $new_attachment_post->post_excerpt ?? $original_attachment_post->post_excerpt ?? ''; // Set new attachment post description (post_content) with fallbacks. $new_attachment_post->post_content = $new_attachment_post->post_content ?? $original_attachment_post->post_content ?? ''; // Set post parent if set in request, else the default of `0` (no parent). $new_attachment_post->post_parent = $new_attachment_post->post_parent ?? 0; // Insert the new attachment post. $new_attachment_id = wp_insert_attachment( wp_slash( (array) $new_attachment_post ), $saved['path'], 0, true ); if ( is_wp_error( $new_attachment_id ) ) { if ( 'db_update_error' === $new_attachment_id->get_error_code() ) { $new_attachment_id->add_data( array( 'status' => 500 ) ); } else { $new_attachment_id->add_data( array( 'status' => 400 ) ); } return $new_attachment_id; } // First, try to use the alt text from the request. If not set, copy the image alt text from the original attachment. $image_alt = isset( $request['alt_text'] ) ? sanitize_text_field( $request['alt_text'] ) : get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ); if ( ! empty( $image_alt ) ) { // update_post_meta() expects slashed. update_post_meta( $new_attachment_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) ); } if ( wp_is_serving_rest_request() ) { /* * Set a custom header with the attachment_id. * Used by the browser/client to resume creating image sub-sizes after a PHP fatal error. */ header( 'X-WP-Upload-Attachment-ID: ' . $new_attachment_id ); } // Generate image sub-sizes and meta. $new_image_meta = wp_generate_attachment_metadata( $new_attachment_id, $saved['path'] ); // Copy the EXIF metadata from the original attachment if not generated for the edited image. if ( isset( $image_meta['image_meta'] ) && isset( $new_image_meta['image_meta'] ) && is_array( $new_image_meta['image_meta'] ) ) { // Merge but skip empty values. foreach ( (array) $image_meta['image_meta'] as $key => $value ) { if ( empty( $new_image_meta['image_meta'][ $key ] ) && ! empty( $value ) ) { $new_image_meta['image_meta'][ $key ] = $value; } } } // Reset orientation. At this point the image is edited and orientation is correct. if ( ! empty( $new_image_meta['image_meta']['orientation'] ) ) { $new_image_meta['image_meta']['orientation'] = 1; } // The attachment_id may change if the site is exported and imported. $new_image_meta['parent_image'] = array( 'attachment_id' => $attachment_id, // Path to the originally uploaded image file relative to the uploads directory. 'file' => _wp_relative_upload_path( $image_file ), ); /** * Filters the meta data for the new image created by editing an existing image. * * @since 5.5.0 * * @param array $new_image_meta Meta data for the new image. * @param int $new_attachment_id Attachment post ID for the new image. * @param int $attachment_id Attachment post ID for the edited (parent) image. */ $new_image_meta = apply_filters( 'wp_edited_image_metadata', $new_image_meta, $new_attachment_id, $attachment_id ); wp_update_attachment_metadata( $new_attachment_id, $new_image_meta ); $response = $this->prepare_item_for_response( get_post( $new_attachment_id ), $request ); $response->set_status( 201 ); $response->header( 'Location', rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $new_attachment_id ) ) ); return $response; } /** * Prepares a single attachment for create or update. * * @since 4.7.0 * * @param WP_REST_Request $request Request object. * @return stdClass|WP_Error Post object. */ protected function prepare_item_for_database( $request ) { $prepared_attachment = parent::prepare_item_for_database( $request ); // Attachment caption (post_excerpt internally). if ( isset( $request['caption'] ) ) { if ( is_string( $request['caption'] ) ) { $prepared_attachment->post_excerpt = $request['caption']; } elseif ( isset( $request['caption']['raw'] ) ) { $prepared_attachment->post_excerpt = $request['caption']['raw']; } } // Attachment description (post_content internally). if ( isset( $request['description'] ) ) { if ( is_string( $request['description'] ) ) { $prepared_attachment->post_content = $request['description']; } elseif ( isset( $request['description']['raw'] ) ) { $prepared_attachment->post_content = $request['description']['raw']; } } if ( isset( $request['post'] ) ) { $prepared_attachment->post_parent = (int) $request['post']; } return $prepared_attachment; } /** * Prepares a single attachment output for response. * * @since 4.7.0 * @since 5.9.0 Renamed `$post` to `$item` to match parent class for PHP 8 named parameter support. * * @param WP_Post $item Attachment object. * @param WP_REST_Request $request Request object. * @return WP_REST_Response Response object. */ public function prepare_item_for_response( $item, $request ) { // Restores the more descriptive, specific name for use within this method. $post = $item; $response = parent::prepare_item_for_response( $post, $request ); $fields = $this->get_fields_for_response( $request ); $data = $response->get_data(); if ( in_array( 'description', $fields, true ) ) { $data['description'] = array( 'raw' => $post->post_content, /** This filter is documented in wp-includes/post-template.php */ 'rendered' => apply_filters( 'the_content', $post->post_content ), ); } if ( in_array( 'caption', $fields, true ) ) { /** This filter is documented in wp-includes/post-template.php */ $caption = apply_filters( 'get_the_excerpt', $post->post_excerpt, $post ); /** This filter is documented in wp-includes/post-template.php */ $caption = apply_filters( 'the_excerpt', $caption ); $data['caption'] = array( 'raw' => $post->post_excerpt, 'rendered' => $caption, ); } if ( in_array( 'alt_text', $fields, true ) ) { $data['alt_text'] = get_post_meta( $post->ID, '_wp_attachment_image_alt', true ); } if ( in_array( 'media_type', $fields, true ) ) { $data['media_type'] = wp_attachment_is_image( $post->ID ) ? 'image' : 'file'; } if ( in_array( 'mime_type', $fields, true ) ) { $data['mime_type'] = $post->post_mime_type; } if ( in_array( 'media_details', $fields, true ) ) { $data['media_details'] = wp_get_attachment_metadata( $post->ID ); // Ensure empty details is an empty object. if ( empty( $data['media_details'] ) ) { $data['media_details'] = new stdClass(); } elseif ( ! empty( $data['media_details']['sizes'] ) ) { foreach ( $data['media_details']['sizes'] as $size => &$size_data ) { if ( isset( $size_data['mime-type'] ) ) { $size_data['mime_type'] = $size_data['mime-type']; unset( $size_data['mime-type'] ); } // Use the same method image_downsize() does. $image_src = wp_get_attachment_image_src( $post->ID, $size ); if ( ! $image_src ) { continue; } $size_data['source_url'] = $image_src[0]; } $full_src = wp_get_attachment_image_src( $post->ID, 'full' ); if ( ! empty( $full_src ) ) { $data['media_details']['sizes']['full'] = array( 'file' => wp_basename( $full_src[0] ), 'width' => $full_src[1], 'height' => $full_src[2], 'mime_type' => $post->post_mime_type, 'source_url' => $full_src[0], ); } } else { $data['media_details']['sizes'] = new stdClass(); } } if ( in_array( 'post', $fields, true ) ) { $data['post'] = ! empty( $post->post_parent ) ? (int) $post->post_parent : null; } if ( in_array( 'source_url', $fields, true ) ) { $data['source_url'] = wp_get_attachment_url( $post->ID ); } if ( in_array( 'missing_image_sizes', $fields, true ) ) { require_once ABSPATH . 'wp-admin/includes/image.php'; $data['missing_image_sizes'] = array_keys( wp_get_missing_image_subsizes( $post->ID ) ); } $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->filter_response_by_context( $data, $context ); $links = $response->get_links(); // Wrap the data in a response object. $response = rest_ensure_response( $data ); foreach ( $links as $rel => $rel_links ) { foreach ( $rel_links as $link ) { $response->add_link( $rel, $link['href'], $link['attributes'] ); } } /** * Filters an attachment returned from the REST API. * * Allows modification of the attachment right before it is returned. * * @since 4.7.0 * * @param WP_REST_Response $response The response object. * @param WP_Post $post The original attachment post. * @param WP_REST_Request $request Request used to generate the response. */ return apply_filters( 'rest_prepare_attachment', $response, $post, $request ); } /** * Prepares attachment links for the request. * * @since 6.9.0 * * @param WP_Post $post Post object. * @return array Links for the given attachment. */ protected function prepare_links( $post ) { $links = parent::prepare_links( $post ); if ( ! empty( $post->post_parent ) ) { $post = get_post( $post->post_parent ); if ( ! empty( $post ) ) { $links['https://api.w.org/attached-to'] = array( 'href' => rest_url( rest_get_route_for_post( $post ) ), 'embeddable' => true, 'post_type' => $post->post_type, 'id' => $post->ID, ); } } return $links; } /** * Retrieves the attachment's schema, conforming to JSON Schema. * * @since 4.7.0 * * @return array Item schema as an array. */ public function get_item_schema() { if ( $this->schema ) { return $this->add_additional_fields_schema( $this->schema ); } $schema = parent::get_item_schema(); $schema['properties']['alt_text'] = array( 'description' => __( 'Alternative text to display when attachment is not displayed.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ); $schema['properties']['caption'] = array( 'description' => __( 'The attachment caption.' ), 'type' => 'object', 'context' => array( 'view', 'edit', 'embed' ), 'arg_options' => array( 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database(). 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database(). ), 'properties' => array( 'raw' => array( 'description' => __( 'Caption for the attachment, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( 'description' => __( 'HTML caption for the attachment, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ), ), ); $schema['properties']['description'] = array( 'description' => __( 'The attachment description.' ), 'type' => 'object', 'context' => array( 'view', 'edit' ), 'arg_options' => array( 'sanitize_callback' => null, // Note: sanitization implemented in self::prepare_item_for_database(). 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database(). ), 'properties' => array( 'raw' => array( 'description' => __( 'Description for the attachment, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), ), 'rendered' => array( 'description' => __( 'HTML description for the attachment, transformed for display.' ), 'type' => 'string', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), ), ); $schema['properties']['media_type'] = array( 'description' => __( 'Attachment type.' ), 'type' => 'string', 'enum' => array( 'image', 'file' ), 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ); $schema['properties']['mime_type'] = array( 'description' => __( 'The attachment MIME type.' ), 'type' => 'string', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ); $schema['properties']['media_details'] = array( 'description' => __( 'Details about the media file, specific to its type.' ), 'type' => 'object', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ); $schema['properties']['post'] = array( 'description' => __( 'The ID for the associated post of the attachment.' ), 'type' => 'integer', 'context' => array( 'view', 'edit' ), ); $schema['properties']['source_url'] = array( 'description' => __( 'URL to the original attachment file.' ), 'type' => 'string', 'format' => 'uri', 'context' => array( 'view', 'edit', 'embed' ), 'readonly' => true, ); $schema['properties']['missing_image_sizes'] = array( 'description' => __( 'List of the missing image sizes of the attachment.' ), 'type' => 'array', 'items' => array( 'type' => 'string' ), 'context' => array( 'edit' ), 'readonly' => true, ); unset( $schema['properties']['password'] ); $this->schema = $schema; return $this->add_additional_fields_schema( $this->schema ); } /** * Handles an upload via raw POST data. * * @since 4.7.0 * @since 6.6.0 Added the `$time` parameter. * * @param string $data Supplied file data. * @param array $headers HTTP headers from the request. * @param string|null $time Optional. Time formatted in 'yyyy/mm'. Default null. * @return array|WP_Error Data from wp_handle_sideload(). */ protected function upload_from_data( $data, $headers, $time = null ) { if ( empty( $data ) ) { return new WP_Error( 'rest_upload_no_data', __( 'No data supplied.' ), array( 'status' => 400 ) ); } if ( empty( $headers['content_type'] ) ) { return new WP_Error( 'rest_upload_no_content_type', __( 'No Content-Type supplied.' ), array( 'status' => 400 ) ); } if ( empty( $headers['content_disposition'] ) ) { return new WP_Error( 'rest_upload_no_content_disposition', __( 'No Content-Disposition supplied.' ), array( 'status' => 400 ) ); } $filename = self::get_filename_from_disposition( $headers['content_disposition'] ); if ( empty( $filename ) ) { return new WP_Error( 'rest_upload_invalid_disposition', __( 'Invalid Content-Disposition supplied. Content-Disposition needs to be formatted as `attachment; filename="image.png"` or similar.' ), array( 'status' => 400 ) ); } if ( ! empty( $headers['content_md5'] ) ) { $content_md5 = array_shift( $headers['content_md5'] ); $expected = trim( $content_md5 ); $actual = md5( $data ); if ( $expected !== $actual ) { return new WP_Error( 'rest_upload_hash_mismatch', __( 'Content hash did not match expected.' ), array( 'status' => 412 ) ); } } // Get the content-type. $type = array_shift( $headers['content_type'] ); // Include filesystem functions to get access to wp_tempnam() and wp_handle_sideload(). require_once ABSPATH . 'wp-admin/includes/file.php'; // Save the file. $tmpfname = wp_tempnam( $filename ); $fp = fopen( $tmpfname, 'w+' ); if ( ! $fp ) { return new WP_Error( 'rest_upload_file_error', __( 'Could not open file handle.' ), array( 'status' => 500 ) ); } fwrite( $fp, $data ); fclose( $fp ); // Now, sideload it in. $file_data = array( 'error' => null, 'tmp_name' => $tmpfname, 'name' => $filename, 'type' => $type, ); $size_check = self::check_upload_size( $file_data ); if ( is_wp_error( $size_check ) ) { return $size_check; } $overrides = array( 'test_form' => false, ); $sideloaded = wp_handle_sideload( $file_data, $overrides, $time ); if ( isset( $sideloaded['error'] ) ) { @unlink( $tmpfname ); return new WP_Error( 'rest_upload_sideload_error', $sideloaded['error'], array( 'status' => 500 ) ); } return $sideloaded; } /** * Parses filename from a Content-Disposition header value. * * As per RFC6266: * * content-disposition = "Content-Disposition" ":" * disposition-type *( ";" disposition-parm ) * * disposition-type = "inline" | "attachment" | disp-ext-type * ; case-insensitive * disp-ext-type = token * * disposition-parm = filename-parm | disp-ext-parm * * filename-parm = "filename" "=" value * | "filename*" "=" ext-value * * disp-ext-parm = token "=" value * | ext-token "=" ext-value * ext-token = * * @since 4.7.0 * * @link https://tools.ietf.org/html/rfc2388 * @link https://tools.ietf.org/html/rfc6266 * * @param string[] $disposition_header List of Content-Disposition header values. * @return string|null Filename if available, or null if not found. */ public static function get_filename_from_disposition( $disposition_header ) { // Get the filename. $filename = null; foreach ( $disposition_header as $value ) { $value = trim( $value ); if ( ! str_contains( $value, ';' ) ) { continue; } list( , $attr_parts ) = explode( ';', $value, 2 ); $attr_parts = explode( ';', $attr_parts ); $attributes = array(); foreach ( $attr_parts as $part ) { if ( ! str_contains( $part, '=' ) ) { continue; } list( $key, $value ) = explode( '=', $part, 2 ); $attributes[ trim( $key ) ] = trim( $value ); } if ( empty( $attributes['filename'] ) ) { continue; } $filename = trim( $attributes['filename'] ); // Unquote quoted filename, but after trimming. if ( str_starts_with( $filename, '"' ) && str_ends_with( $filename, '"' ) ) { $filename = substr( $filename, 1, -1 ); } } return $filename; } /** * Retrieves the query params for collections of attachments. * * @since 4.7.0 * @since 6.9.0 Extends the `media_type` and `mime_type` request arguments to support array values. * * @return array Query parameters for the attachment collection as an array. */ public function get_collection_params() { $params = parent::get_collection_params(); $params['status']['default'] = 'inherit'; $params['status']['items']['enum'] = array( 'inherit', 'private', 'trash' ); $media_types = array_keys( $this->get_media_types() ); $params['media_type'] = array( 'default' => null, 'description' => __( 'Limit result set to attachments of a particular media type or media types.' ), 'type' => 'array', 'items' => array( 'type' => 'string', 'enum' => $media_types, ), ); $params['mime_type'] = array( 'default' => null, 'description' => __( 'Limit result set to attachments of a particular MIME type or MIME types.' ), 'type' => 'array', 'items' => array( 'type' => 'string', ), ); return $params; } /** * Handles an upload via multipart/form-data ($_FILES). * * @since 4.7.0 * @since 6.6.0 Added the `$time` parameter. * * @param array $files Data from the `$_FILES` superglobal. * @param array $headers HTTP headers from the request. * @param string|null $time Optional. Time formatted in 'yyyy/mm'. Default null. * @return array|WP_Error Data from wp_handle_upload(). */ protected function upload_from_file( $files, $headers, $time = null ) { if ( empty( $files ) ) { return new WP_Error( 'rest_upload_no_data', __( 'No data supplied.' ), array( 'status' => 400 ) ); } // Verify hash, if given. if ( ! empty( $headers['content_md5'] ) ) { $content_md5 = array_shift( $headers['content_md5'] ); $expected = trim( $content_md5 ); $actual = md5_file( $files['file']['tmp_name'] ); if ( $expected !== $actual ) { return new WP_Error( 'rest_upload_hash_mismatch', __( 'Content hash did not match expected.' ), array( 'status' => 412 ) ); } } // Pass off to WP to handle the actual upload. $overrides = array( 'test_form' => false, ); // Bypasses is_uploaded_file() when running unit tests. if ( defined( 'DIR_TESTDATA' ) && DIR_TESTDATA ) { $overrides['action'] = 'wp_handle_mock_upload'; } $size_check = self::check_upload_size( $files['file'] ); if ( is_wp_error( $size_check ) ) { return $size_check; } // Include filesystem functions to get access to wp_handle_upload(). require_once ABSPATH . 'wp-admin/includes/file.php'; $file = wp_handle_upload( $files['file'], $overrides, $time ); if ( isset( $file['error'] ) ) { return new WP_Error( 'rest_upload_unknown_error', $file['error'], array( 'status' => 500 ) ); } return $file; } /** * Retrieves the supported media types. * * Media types are considered the MIME type category. * * @since 4.7.0 * * @return array Array of supported media types. */ protected function get_media_types() { $media_types = array(); foreach ( get_allowed_mime_types() as $mime_type ) { $parts = explode( '/', $mime_type ); if ( ! isset( $media_types[ $parts[0] ] ) ) { $media_types[ $parts[0] ] = array(); } $media_types[ $parts[0] ][] = $mime_type; } return $media_types; } /** * Determine if uploaded file exceeds space quota on multisite. * * Replicates check_upload_size(). * * @since 4.9.8 * * @param array $file $_FILES array for a given file. * @return true|WP_Error True if can upload, error for errors. */ protected function check_upload_size( $file ) { if ( ! is_multisite() ) { return true; } if ( get_site_option( 'upload_space_check_disabled' ) ) { return true; } $space_left = get_upload_space_available(); $file_size = filesize( $file['tmp_name'] ); if ( $space_left < $file_size ) { return new WP_Error( 'rest_upload_limited_space', /* translators: %s: Required disk space in kilobytes. */ sprintf( __( 'Not enough space to upload. %s KB needed.' ), number_format( ( $file_size - $space_left ) / KB_IN_BYTES ) ), array( 'status' => 400 ) ); } if ( $file_size > ( KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ) ) ) { return new WP_Error( 'rest_upload_file_too_big', /* translators: %s: Maximum allowed file size in kilobytes. */ sprintf( __( 'This file is too big. Files must be less than %s KB in size.' ), get_site_option( 'fileupload_maxk', 1500 ) ), array( 'status' => 400 ) ); } // Include multisite admin functions to get access to upload_is_user_over_quota(). require_once ABSPATH . 'wp-admin/includes/ms.php'; if ( upload_is_user_over_quota( false ) ) { return new WP_Error( 'rest_upload_user_quota_exceeded', __( 'You have used your space quota. Please delete files before uploading.' ), array( 'status' => 400 ) ); } return true; } /** * Gets the request args for the edit item route. * * @since 5.5.0 * @since 6.9.0 Adds flips capability and editable fields for the newly-created attachment post. * * @return array */ protected function get_edit_media_item_args() { $args = array( 'src' => array( 'description' => __( 'URL to the edited image file.' ), 'type' => 'string', 'format' => 'uri', 'required' => true, ), // The `modifiers` param takes precedence over the older format. 'modifiers' => array( 'description' => __( 'Array of image edits.' ), 'type' => 'array', 'minItems' => 1, 'items' => array( 'description' => __( 'Image edit.' ), 'type' => 'object', 'required' => array( 'type', 'args', ), 'oneOf' => array( array( 'title' => __( 'Flip' ), 'properties' => array( 'type' => array( 'description' => __( 'Flip type.' ), 'type' => 'string', 'enum' => array( 'flip' ), ), 'args' => array( 'description' => __( 'Flip arguments.' ), 'type' => 'object', 'required' => array( 'flip', ), 'properties' => array( 'flip' => array( 'description' => __( 'Flip direction.' ), 'type' => 'object', 'required' => array( 'horizontal', 'vertical', ), 'properties' => array( 'horizontal' => array( 'description' => __( 'Whether to flip in the horizontal direction.' ), 'type' => 'boolean', ), 'vertical' => array( 'description' => __( 'Whether to flip in the vertical direction.' ), 'type' => 'boolean', ), ), ), ), ), ), ), array( 'title' => __( 'Rotation' ), 'properties' => array( 'type' => array( 'description' => __( 'Rotation type.' ), 'type' => 'string', 'enum' => array( 'rotate' ), ), 'args' => array( 'description' => __( 'Rotation arguments.' ), 'type' => 'object', 'required' => array( 'angle', ), 'properties' => array( 'angle' => array( 'description' => __( 'Angle to rotate clockwise in degrees.' ), 'type' => 'number', ), ), ), ), ), array( 'title' => __( 'Crop' ), 'properties' => array( 'type' => array( 'description' => __( 'Crop type.' ), 'type' => 'string', 'enum' => array( 'crop' ), ), 'args' => array( 'description' => __( 'Crop arguments.' ), 'type' => 'object', 'required' => array( 'left', 'top', 'width', 'height', ), 'properties' => array( 'left' => array( 'description' => __( 'Horizontal position from the left to begin the crop as a percentage of the image width.' ), 'type' => 'number', ), 'top' => array( 'description' => __( 'Vertical position from the top to begin the crop as a percentage of the image height.' ), 'type' => 'number', ), 'width' => array( 'description' => __( 'Width of the crop as a percentage of the image width.' ), 'type' => 'number', ), 'height' => array( 'description' => __( 'Height of the crop as a percentage of the image height.' ), 'type' => 'number', ), ), ), ), ), ), ), ), 'rotation' => array( 'description' => __( 'The amount to rotate the image clockwise in degrees. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'integer', 'minimum' => 0, 'exclusiveMinimum' => true, 'maximum' => 360, 'exclusiveMaximum' => true, ), 'x' => array( 'description' => __( 'As a percentage of the image, the x position to start the crop from. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), 'y' => array( 'description' => __( 'As a percentage of the image, the y position to start the crop from. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), 'width' => array( 'description' => __( 'As a percentage of the image, the width to crop the image to. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), 'height' => array( 'description' => __( 'As a percentage of the image, the height to crop the image to. DEPRECATED: Use `modifiers` instead.' ), 'type' => 'number', 'minimum' => 0, 'maximum' => 100, ), ); /* * Get the args based on the post schema. This calls `rest_get_endpoint_args_for_schema()`, * which also takes care of sanitization and validation. */ $update_item_args = $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ); if ( isset( $update_item_args['caption'] ) ) { $args['caption'] = $update_item_args['caption']; } if ( isset( $update_item_args['description'] ) ) { $args['description'] = $update_item_args['description']; } if ( isset( $update_item_args['title'] ) ) { $args['title'] = $update_item_args['title']; } if ( isset( $update_item_args['post'] ) ) { $args['post'] = $update_item_args['post']; } if ( isset( $update_item_args['alt_text'] ) ) { $args['alt_text'] = $update_item_args['alt_text']; } return $args; } } دستگاه تست عایقی های پات و میگر GPS9020ADI - ابزارونیک
علاقه مندی
ورود / ثبت نام
  • محصولات
    • ابزار دقیق
      • اسیلوسکوپ
      • USB تستر
      • تستر SMD
      • تستر شبکه و زوج یاب
      • تستر ولتاژ دوشاخ
      • بادسنج
      • دورسنج
      • صوت سنج
      • دماسنج و رطوبت سنج
      • فازیاب
      • متر لیزری
      • کلمپ متر
      • لوکس متر
      • LCR متر
      • مولتی متر
      • وات متر
    • قطعات و تجهیزات الکترونیک
      • آی سی
      • انواع ترانزیستور
      • انواع خازن
      • انواع دیود
      • انواع کانکتور
      • انواع مقاومت
    • ابزارآلات برقی
      • التراسونیک
      • پری هیتر
      • پیچ گوشتی برقی و شارژی
      • تفنگ چسب حرارتی
      • دستگاه پاک کننده چسب
      • دستگاه هیترو هویه
      • سپراتور
      • سشوار صنعتی
      • قلع کش برقی
      • لامپ UV
      • مینی فرز و مینی دریل
      • هویه قلمی
    • ابزار دستی
      • آچار آلن
      • آچار بکس
      • آچار پرس شبکه
      • آچار پرس کانکتور
      • آچار فرانسه
      • آچار پانچ و کروز
      • آی سی کش
      • ابزار لحیم کاری
      • اسپاتول و قاب باز کن
      • انبر دست
      • انبر قفلی
      • انواع گیره
      • پایه هویه
      • پنس
      • پیچ گوشتی
      • تاچ کش
      • جا الکلی
      • خار باز کن
      • دم باریک
      • سوهان
      • سیم چین
      • سیم لخت کن
    • لوپ و ذره‌بین
      • لوپ دو چشمی
      • لوپ سه چشمی
      • لوپ دیجیتال
      • تجهیزات جانبی لوپ
    • سایر
  • دوربین مداربسته
  • تماس با ما
  • درباره ما
0 مقایسه
20 محصول / 139,060,000 تومان
مارا دنبال کنید
منو
20 محصول / 139,060,000 تومان
View cart “دستگاه اسیلوسکوپ مدل DSO-2D10” has been added to your cart.
بزرگنمایی تصویر
Home ابزارآلات برقی منبع تغذیه و سوئیچینگ دستگاه تست عایقی های پات و میگر GPS9020ADI
دستگاه تست عایقی های پات GPS-9020AD 96,500,000 تومان
بازگشت به محصولات
ال سی آر متر یونیتی مدل UT612 9,895,000 تومان

دستگاه تست عایقی های پات و میگر GPS9020ADI

120,000,000 تومان

دستگاه تست عایقی های پات و میگر AC/DC Hipot Tester مدل GPS-9020ADI
مقایسه
افزودن به علاقه مندی
Categories: منبع تغذیه و سوئیچینگ, ابزار دقیق
Share:
  • Description
  • Reviews (0)
  • خرید و فروش
Description
  • خروجی  ACW: از 5 کیلو ولت / 20 میلی آمپر (9020AD/9020A/9020ADI)
  • خروجی DCW:  از 1 کیلو ولت / 10 میلی آمپر (9020AD/9020ADI)
  • خروجی امتیاز IR: از 1 کیلو ولت / 10GΩ (9020ADI)
  • قابلیت تخلیه سریع DC، حفاظت از شوک الکتریکی و تشخیص قوس
  • زمان افزایش ولتاژ، زمان تست و زمان سقوط را می توان به طور دلخواه در عرض 999.9 ثانیه تنظیم کرد.
  • دارای رابط HANDLER (PLC) و رابط RS-232C
  • دارای ژنراتور سینوسی قابل کنترل: می توان آن را روی 50 یا 60 هرتز تنظیم کرد
  • هنگامی که خروجی AC، دیگر توسط ولتاژ خط محدود نمی شود
  • تقویت کننده توان خطی: اعوجاج شکل موج ولتاژ کم است. کنترل ساده است و قابلیت اطمینان بالا است
  • بازرسی عملکرد ایمنی لوازم خانگی، ترانسفورماتورها، تجهیزات الکتریکی و قطعات الکترونیکی
  • ولتاژ خروجی: 0.050kV-1.000kV با دقت 0.001 ولت
  • رنج اندازه گیری: 0.02MΩ to 10GΩ
Reviews (0)

Reviews

There are no reviews yet.

Be the first to review “دستگاه تست عایقی های پات و میگر GPS9020ADI” لغو پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

خرید و فروش

Related products

مقایسه

دستگاه اسیلوسکوپ مدل DSO-2D10

ابزار دقیق, اسیلوسکوپ
15,150,000 تومان
  • اسیلوسکوپ 100 مگاهرتز 2 کاناله + حافظه دیجیتال
  • سرعت نمونه برداری 1GSa/S
  • صفحه نمایشگر TFT رنگی 7 اینچ
  • دارای 2 عدد پروب
  • فانکشن ژنراتور قابل برنامه ریزي 25 مگاهرتز
  • فانکشن FFT
  • 8M RECORD LENGTH
  • 14 مدل تریگر
  • ولتمتر 2 کاناله
  • اتصال به کامپیوتر با پورت USB
  • 32 نوع اندازه گیری اتوماتیک
  • USB FLASH
افزودن به علاقه مندی
Add to cart
مشاهده سریع
unit
204+
204+
مقایسه

آمپرمتر کلمپی یونیتی +UNI_T UT204

ابزار دقیق, کلمپ متر
3,000,000 تومان
آمپرمتر کلمپی یونیتی +UN_T UT-204
  1. قابلیت پرکاربرد ردیابی فازغیر تماسی NCV
  2. نمایش اعداد تا 6000
  3. مجهز به قابلیت DATA HOLD
  4. قابلیت تست پیوستگی و دیود
افزودن به علاقه مندی
Add to cart
مشاهده سریع
unit
201+
201 PLUS
مقایسه

آمپرمتر کلمپی یونیتی +UNI_T UT201

ابزار دقیق, کلمپ متر
1,295,000 تومان
آمپرمتر کلمپی یونیتی +UNI_T UT201
  1. قابلیت اندازه گیری بدون تماس و آسیب به کابل ها را داراست.
  2. دارای قابلیت ردیابی فاز NCV و قابلیت TrueRMS
افزودن به علاقه مندی
Add to cart
مشاهده سریع
proskit
آچار فرانسه 2.5 اینچی پروسکیت ProsKit HW-003مولتی متر اتورنج دیجیتال پروسکیت ProsKit MT-1232 مولتی متر سلکتور دیجیتال پروسکیت ProsKit MT-1280
مقایسه

مولتی متر سلکتور دیجیتال پروسکیت ProsKit MT-1280

ابزار دقیق, مولتی متر
2,000,000 تومان

مشخصات فنی مولتی متر پروسکیت مدل ProsKit MT-1280:

  • مولتی متر دیجیتال
  • دستی
  • سلکتوری
  • صفحه نمایش 1/2 3 دیجیت 1999 کانت
  • دارای صفحه نمایش بزرگ و با کیفیت
  • اندازه گیری ولتاژ AC از 2 تا 750 ولت
  • اندازه گیری ولتاژ DC از 200 میلی ولت تا 1000 ولت
  • اندازه گیری جریان DC از 200 میکرو آمپر تا 20 آمپر
  • اندازه گیری جریان AC از 200 میلی آمپر تا 120 آمپر
  • اندازه گیری مقاومت از 200 اهم تا 200 مگا اهم
  • اندازه گیری خازن از 20 نانو فاراد تا 200 میکرو فاراد
  • اندازه گیری فرکانس از 1هرتز تا 10 مگاهرتز
  • دماسنج از منفی 20 تا 1000 درجه سانتیگراد
  • دارای تست دیود
  • دارای تست پیوستگی
  • تست ترانزیستور
  • دارای استاندارد CAT III 1000V
  • دارای استاندارد CE
  • دارای استاندارد IEN61010-1
  • دارای فیوز محافظ از دستگاه
  • دارای نور صفحه نمایش
  • دارای Data HOLD
  • تغذیه دستگاه یک عدد باتری کتابی 9V
  • دارای پراب دما سنج، پراب تست ترانزیستور، و پراب مولتی متر
افزودن به علاقه مندی
Add to cart
مشاهده سریع
hioki
4252
مقایسه

مولتی متر هیوکی مدل DT4252

ابزار دقیق, مولتی متر
8,000,000 تومان
مولتی متر هیوکی مدل DT4252 از شرکت هیوکی یک دستگاه اندازه‌گیری دیجیتال با عملکرد و دقت بالا میباشد. ساخت کشور ژاپن
افزودن به علاقه مندی
Add to cart
مشاهده سریع
proskit
فازیاب غیر تماسی پروسکیت مدل nt-309
مقایسه

تستر ولتاژ و فازیاب غیر تماسی پروسکیت – مدل Proskit NT-309

ابزار دقیق, کلمپ متر
785,000 تومان
فاز تستر غیر تماسی قابلیت تشخیص سطوح ولتاژ از 12 تا 1000 ولت متناوب از روی کابل و بدون نیاز
افزودن به علاقه مندی
Add to cart
مشاهده سریع
مولتی متر هی آکی
مقایسه

مولتی متر هی او کی

ابزار دقیق, مولتی متر
1,200,000 تومان

منبع تغذیه :

باتری

افزودن به علاقه مندی
Add to cart
مشاهده سریع
unit
202BT
مقایسه

آمپرمتر کلمپی یونیتی UNI_T UT202BT

ابزار دقیق, کلمپ متر
3,570,000 تومان
آمپرمتر کلمپی یونیتی UNI_T UT202BT
  1. دستگاه قابلیت تنظیم خودکار بازه سنجش را دارد.
  2. دستگاه قابلیت مکث در حین اندازه گیری و نمایش پیک بار را دارد.
افزودن به علاقه مندی
Add to cart
مشاهده سریع
PROSKIT
HIKVISION
SUNSHINE-TOOLS
DAHUA
Hioki
ANALOG-DVICES
RELIFE
GOOT
yaxun
MINI-CIRCUITS
UNIT
RIGOL
FLUKE
quick
logo12

ابزارونیک مرجع ابزارآلات الکترونیکی

  • ایران تهران خیابان جمهوری
  • 021-66751084
  • info@abzaronic.com
آخرین مقالات
  • ایران وود مارت بهترین انتخاب
  • electronics-2-blog-7
    بهترین انتخاب در کامپیوتر و لپ تاب
  • دکوراسیون داخلی خونه
  • میز های ایرانی در برند مختلف
پر امتیازترین محصولات
  • 213 کلمپ آمپرمتر دیجیتال یونیتی UNI_T UT213C 4,880,000 تومان
  • ارت سنج میله ای یونیتی UNI_T UT521 12,700,000 تومان
  • Placeholder مینی ترمومتر لیزری 300 درجه یونیتی UNI_T UT-306A
لینک های مفید
  • قوانین و مقررات
  • سوالات متداول
  • خبرنامه
  • تماس با ما
  • اخبار جدید
  • خرید های قدیمی
منوی فوتر
  • اینستاگرام
  • تماس با ما
محتوای این سایت شخصی می‌باشد.
  • منو
  • دسته بندی ها
  • محصولات
    • ابزار دقیق
      • اسیلوسکوپ
      • USB تستر
      • تستر SMD
      • تستر شبکه و زوج یاب
      • تستر ولتاژ دوشاخ
      • بادسنج
      • دورسنج
      • صوت سنج
      • دماسنج و رطوبت سنج
      • فازیاب
      • متر لیزری
      • کلمپ متر
      • لوکس متر
      • LCR متر
      • مولتی متر
      • وات متر
    • قطعات و تجهیزات الکترونیک
      • آی سی
      • انواع ترانزیستور
      • انواع خازن
      • انواع دیود
      • انواع کانکتور
      • انواع مقاومت
    • ابزارآلات برقی
      • التراسونیک
      • پری هیتر
      • پیچ گوشتی برقی و شارژی
      • تفنگ چسب حرارتی
      • دستگاه پاک کننده چسب
      • دستگاه هیترو هویه
      • سپراتور
      • سشوار صنعتی
      • قلع کش برقی
      • لامپ UV
      • مینی فرز و مینی دریل
      • هویه قلمی
    • ابزار دستی
      • آچار آلن
      • آچار بکس
      • آچار پرس شبکه
      • آچار پرس کانکتور
      • آچار فرانسه
      • آچار پانچ و کروز
      • آی سی کش
      • ابزار لحیم کاری
      • اسپاتول و قاب باز کن
      • انبر دست
      • انبر قفلی
      • انواع گیره
      • پایه هویه
      • پنس
      • پیچ گوشتی
      • تاچ کش
      • جا الکلی
      • خار باز کن
      • دم باریک
      • سوهان
      • سیم چین
      • سیم لخت کن
    • لوپ و ذره‌بین
      • لوپ دو چشمی
      • لوپ سه چشمی
      • لوپ دیجیتال
      • تجهیزات جانبی لوپ
    • سایر
  • دوربین مداربسته
  • تماس با ما
  • درباره ما
  • محصولات
    • ابزار دقیق
      • اسیلوسکوپ
      • USB تستر
      • تستر SMD
      • تستر شبکه و زوج یاب
      • تستر ولتاژ دوشاخ
      • بادسنج
      • دورسنج
      • صوت سنج
      • دماسنج و رطوبت سنج
      • فازیاب
      • متر لیزری
      • کلمپ متر
      • لوکس متر
      • LCR متر
      • مولتی متر
      • وات متر
    • قطعات و تجهیزات الکترونیک
      • آی سی
      • انواع ترانزیستور
      • انواع خازن
      • انواع دیود
      • انواع کانکتور
      • انواع مقاومت
    • ابزارآلات برقی
      • التراسونیک
      • پری هیتر
      • پیچ گوشتی برقی و شارژی
      • تفنگ چسب حرارتی
      • دستگاه پاک کننده چسب
      • دستگاه هیترو هویه
      • سپراتور
      • سشوار صنعتی
      • قلع کش برقی
      • لامپ UV
      • مینی فرز و مینی دریل
      • هویه قلمی
    • ابزار دستی
      • آچار آلن
      • آچار بکس
      • آچار پرس شبکه
      • آچار پرس کانکتور
      • آچار فرانسه
      • آچار پانچ و کروز
      • آی سی کش
      • ابزار لحیم کاری
      • اسپاتول و قاب باز کن
      • انبر دست
      • انبر قفلی
      • انواع گیره
      • پایه هویه
      • پنس
      • پیچ گوشتی
      • تاچ کش
      • جا الکلی
      • خار باز کن
      • دم باریک
      • سوهان
      • سیم چین
      • سیم لخت کن
    • لوپ و ذره‌بین
      • لوپ دو چشمی
      • لوپ سه چشمی
      • لوپ دیجیتال
      • تجهیزات جانبی لوپ
    • سایر
  • دوربین مداربسته
  • تماس با ما
  • درباره ما
  • علاقه مندی
  • مقایسه
  • ورود / ثبت نام
سبد خرید
بستن (Esc)

ورود

بستن (Esc)

رمز عبور را فراموش کرده اید؟

هنوز حساب کاربری ندارید؟

ایجاد حساب کاربری
برای دیدن محصولات که دنبال آن هستید تایپ کنید.