如何从自有APP上传相册视频至YouTube(未列出)?求POST请求方案
Got it, let's walk through exactly how to implement this—since you already have your OAuth token, the main piece is using YouTube's Resumable Upload flow (the standard for reliable video uploads, especially for larger files) with the YouTube Data API. Here's a step-by-step breakdown with example code:
1. First: Prepare Video Metadata
You need to send JSON metadata defining your video's title, description, and privacy status (set to unlisted). Here's what that looks like:
{ "snippet": { "title": "My App Uploaded Video", "description": "This video was uploaded directly from my custom app!", "categoryId": "22" // Pick a category ID matching your content (22 = People & Blogs, adjust as needed) }, "status": { "privacyStatus": "unlisted", "selfDeclaredMadeForKids": false // Set to true if your content is made for kids } }
2. Initialize a Resumable Upload Session
First, send a POST request to YouTube's API to get a dedicated upload URL. This URL will be used to send your actual video file.
Example Code (Android with OkHttp)
OkHttpClient client = new OkHttpClient(); // Replace with your metadata JSON string String metadataJson = "{\"snippet\":{\"title\":\"My App Uploaded Video\",\"description\":\"Uploaded from my app\",\"categoryId\":\"22\"},\"status\":{\"privacyStatus\":\"unlisted\",\"selfDeclaredMadeForKids\":false}}"; // Calculate your video file's size (replace with your actual file path) File videoFile = new File("/path/to/your/selected/video.mp4"); long videoFileSize = videoFile.length(); Request initRequest = new Request.Builder() .url("https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status") .post(RequestBody.create(metadataJson, MediaType.parse("application/json"))) .addHeader("Authorization", "Bearer " + YOUR_ACCESS_TOKEN) // Replace with your token .addHeader("Content-Type", "application/json; charset=UTF-8") .addHeader("X-Upload-Content-Type", "video/mp4") // Match your video's MIME type .addHeader("X-Upload-Content-Length", String.valueOf(videoFileSize)) .build(); try (Response response = client.newCall(initRequest).execute()) { if (response.isSuccessful()) { // Extract the upload URL from the "Location" response header String uploadUrl = response.header("Location"); // Save this URL—you'll need it for the next step uploadVideoFile(client, uploadUrl, videoFile); } else { // Handle errors (e.g., token expired, missing permissions) String errorDetails = response.body().string(); Log.e("YouTubeUpload", "Failed to init session: " + errorDetails); } } catch (IOException e) { e.printStackTrace(); }
3. Upload the Video File
Use the upload URL from step 2 to send a PUT request with your video file as the request body.
Example Upload Code (Android)
private void uploadVideoFile(OkHttpClient client, String uploadUrl, File videoFile) { RequestBody videoBody = RequestBody.create(videoFile, MediaType.parse("video/mp4")); Request uploadRequest = new Request.Builder() .url(uploadUrl) .put(videoBody) .addHeader("Content-Type", "video/mp4") .addHeader("Content-Length", String.valueOf(videoFile.length())) .build(); try (Response uploadResponse = client.newCall(uploadRequest).execute()) { if (uploadResponse.isSuccessful()) { // Upload succeeded! The response body has your video's details (including videoId) String responseBody = uploadResponse.body().string(); Log.d("YouTubeUpload", "Upload complete! Video data: " + responseBody); // Parse the response to get the videoId if you need it for future actions } else { String errorDetails = uploadResponse.body().string(); Log.e("YouTubeUpload", "Upload failed: " + errorDetails); // If you get a 401 error, your token is expired—you'll need to refresh it } } catch (IOException e) { e.printStackTrace(); // If the upload is interrupted (e.g., network drop), just re-run this method with the same uploadUrl // YouTube will automatically resume from where it left off } }
4. Key Things to Remember
- Permission Check: Make sure your OAuth token includes the
https://www.googleapis.com/auth/youtube.uploadscope. Without this, YouTube will reject your upload requests with a 403 error. - MIME Types: Double-check your video's MIME type (e.g.,
video/mp4for MP4,video/quicktimefor MOV). Using the wrong type can cause upload failures. - Resumable Uploads: If your upload gets interrupted (network issues, app backgrounded), just re-send the PUT request with the same upload URL—no need to re-initialize the session or re-upload the entire file.
- Error Handling: Common issues include expired tokens (401), missing scopes (403), oversized files (YouTube's limit is 128GB or 12 hours, whichever is smaller), and unsupported video formats.
Bonus: iOS Example Snippet
If you're building for iOS, the flow is identical—here's a quick snippet using URLSession:
func initUploadSession(accessToken: String, videoFileURL: URL) { let metadata: [String: Any] = [ "snippet": [ "title": "My iOS App Upload", "description": "Uploaded from my iOS app", "categoryId": "22" ], "status": [ "privacyStatus": "unlisted", "selfDeclaredMadeForKids": false ] ] guard let metadataData = try? JSONSerialization.data(withJSONObject: metadata) else { print("Failed to serialize metadata") return } let videoFileSize = try? FileManager.default.attributesOfItem(atPath: videoFileURL.path)[.size] as? Int64 ?? 0 var request = URLRequest(url: URL(string: "https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status")!) request.httpMethod = "POST" request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization") request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type") request.setValue("video/mp4", forHTTPHeaderField: "X-Upload-Content-Type") request.setValue(String(videoFileSize ?? 0), forHTTPHeaderField: "X-Upload-Content-Length") request.httpBody = metadataData URLSession.shared.dataTask(with: request) { data, response, error in guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200, let uploadUrl = httpResponse.allHeaderFields["Location"] as? String else { print("Session init failed: \(error?.localizedDescription ?? "Unknown error")") return } self.uploadVideo(to: uploadUrl, videoFileURL: videoFileURL) }.resume() } func uploadVideo(to uploadUrl: String, videoFileURL: URL) { var request = URLRequest(url: URL(string: uploadUrl)!) request.httpMethod = "PUT" request.setValue("video/mp4", forHTTPHeaderField: "Content-Type") URLSession.shared.uploadTask(with: request, fromFile: videoFileURL) { data, response, error in guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { print("Upload failed: \(error?.localizedDescription ?? "Unknown error")") return } if let data = data, let responseStr = String(data: data, encoding: .utf8) { print("Upload success! Response: \(responseStr)") } }.resume() }
内容的提问来源于stack exchange,提问作者podgradle

