[완료]perl WWW::Mechanize로 파일 업로드 질문입니다.

ipes4579의 이미지

mechanize 의 post 방식을 사용해 파일을 업로드 하려고 합니다.

코드는 대략 다음과 같습니다.

$browser->post("$url", 
			    [
			     "form_key" => $form_key,
			     "summary" => "안녕하세요",
			     "details" => "hhh",
			     "input_file[]" => ["1.pdf", 'Content-Type' => 'application/pdf'],
			     "upload1" => upload1,
			    ],
			   'Content_Type' => 'form-data',
);

이렇게 보내면

 
HTTP::Message content must be bytes at /usr/local/share/perl/5.10.1/HTTP/Request/Common.pm line 97 

다음과 같은 에러 메시지를 내뿜고 죽어버립니다. 아, 참고로 한글을 모두 영어로 바꿔서 보내면 잘 보내집니다.

구글링을 해 보니 분명 utf8 문제 같은데, 거기서 말하는대로

LWP, WWW::Mechanize, HTTP~~~ 등등을 다 업그레이드 하고
/usr/local/share/perl/5.10.1/HTTP/Request/Common.pm 파일에

if( utf8::is_utf8($content)){ $content =  Encode::decode('utf8',$content);}

를 추가해도 똑같습니다. 무슨 해결방법 없을까요?
raymundo의 이미지

펄 모듈 소스를 직접 수정하실 것까지는 없어보이고...

일단 제가 먼저 질문을 하고 싶은데, 본문에 쓰신 소스코드는 현재 use utf8 프라그마가 사용되어 있는 상태 같은데 맞나요?

만일 맞다면

"summary" => "안녕하세요",
대신에
"summary" => encode("UTF-8", "안녕하세요"),   # 해당 웹사이트 인코딩에 맞춰서 UTF-8 또는 EUC-KR

이렇게 한 번 해보시지요.

좋은 하루 되세요!

ipes4579의 이미지

use utf8; 프라그마 사용하고 있습니다.

$browser->post("$url", 
			    [
			     "form_key" => $form_key,
			     "summary" => encode("UTF-8", "안녕하세요"),
			     "details" => "hhh",
			     "input_file[]" => ["1.pdf", 'Content-Type' => 'application/pdf'],
			     "upload1" => upload1,
			    ],
			   'Content_Type' => 'form-data',
);

HTTP::Message content must be bytes at /usr/local/share/perl/5.10.1/HTTP/Request/Common.pm line 97 

같은 에러가 나오네요. -_ㅠ 혹시몰라
"summary" => encode("UTF-8", "abcd")

와 같이 영어로 바꾸니 영어는 잘 포스팅 됩니다. 근데 한글이 계속 문제네요..
raymundo의 이미지

으음... 영어면 잘 되고 한글이면 안 된다면 저것밖에 안 떠오르는데 말이죠;;

근데 제가 집에 와서 비슷하게 만들어서 해봤는데... 에러가 안 나요;

스트로베리 펄 5.10
WWW::Mechanize 1.68
HTTP::Request::Common 5.824 - 최신은 6.00 이던데 업그레이드하려니 도중에 에러가 나서 실패

이걸 가지고 해봤는데 전혀 저런 에러가 안 나서... 전 두 손 들었습니다 ^^;

해결되시면 꼭 여기에 달아주세요, 나중에라도 와서 저도 배우게요. 해결되길 기원합니다~

좋은 하루 되세요!

ipes4579의 이미지

raymundo님! 드디어 됐습니다. 이틀째 헤매고 있었는데 드디어 되었습니다! ㅠ

분명 raymundo님의 모듈들과 제 모듈들의 버전이 같거나 오히려 더 높은데 왜 제꺼에서만 안되나 고민하다가 발견했습니다.

사실 raymundo 님께 거짓말 한 것이 있는데, 저는 use utf8; 프라그마를 사용한 것이 아니라 utf encoding 'utf8'; 프라그마를 사용하고 있었습니다.

거짓말하려던 건 아니었고, 저는 똑같은 건 줄 알았었습니다. -_-; 근데 댓글보고 혹시나 해서 바꿔보니 잘 작동 되는 것을 보고는 정말 놀랐네요.

작동되는 풀 코드 첨부합니다. 네이버 scm인 nforge에 개인적인 프로젝트를 하면서 매일 pdf 파일 업로드 하는 귀찮은 부분을 자동화 하려고 했을 뿐인데

생각보다 오래 걸렸네요. 정말 감사합니다 ! ^^

#!/usr/bin/perl -w
 
use strict;
use warnings;
use WWW::Mechanize;
use utf8;
#use encoding 'utf-8';   #이걸 주석 처리해주니 잘 되는군요.
use Encode qw(encode);
 
my $browser = WWW::Mechanize->new();
 
=for paros
$ENV{HTTP_PROXY} = 'localhost:8080';
$browser->proxy('http', 'http://127.0.0.1:8080');
=cut
 
my $res = $browser->get("http://(주소)/account/login.php", autocheck => 1);
my $form_key;
my $content = $browser->content;
if( $content =~ /form_key\" value=\"(.+)\" type=\"hidden\"/ )
{
    $form_key = $1;
}
$browser->post("http://(주소)/account/login.php",
	       [
		'form_key' => $form_key,
		'login' => 1,
		'form_loginname' => "아이디",
		'form_pw' => "패스워드",
	       ]);
 
$res = $browser->get( "http://(주소)/projects/community/report/add");
$content = $res->decoded_content;
 
if( $content =~ /form_key\" value=\"(.+)\"/ )
{
    $form_key = $1;
}
else
{
    print "Can not find a form_key\n";
    return -1;
}
 
$browser->post("http://192.168.50.1:8080/projects/community/report", 
	       [
		"form_key" => $form_key,
		"summary" => encode("UTF-8", '제목'),
		"details" => encode("UTF-8", '내용'),
		"input_file[]" => ["/path/to/my.pdf" => encode("UTF-8", "오늘의pdf.pdf")],		
	       ],
	       'Content_Type' => 'form-data', 
    );

aero의 이미지

use encoding은 설계가 잘못된 모듈로 잘못쓰면
ASCII영역을 넘어가는 바이너리 데이터를 다룰때 마구 꼬이게 됩니다.

Perl 유니코드/한글 처리는
http://gypark.pe.kr/wiki/Perl/%ED%95%9C%EA%B8%80
http://bit.ly/4SQUCL

를 읽어보시길 추천드립니다.

ipes4579의 이미지

좋은 글인 것 같습니다. 정독하면서 유니코드에 대해 혼란한 부분을 많이 정리했습니다. 감사합니다 ^^

외국서적만으로 공부하다보니 항상 한글 처리에서 필연적으로 삽질을 하네요. -_ㅠ

raymundo의 이미지

ㅎㅎㅎㅎㅎㅎㅎㅎ 그러셨군요. 다행입니다.

근데 그럼 아예 encode도 할 필요 없이 그냥

# 소스코드는 UTF-8로 인코딩되어 있고
use utf8;  # 이 프라그마 쓰고
 
# 중간생략
$browser->post( 어쩌고저쩌고...
"summary" => "안녕하세요"    # 제일 처음 쓰셨던 것처럼
)

이 상태로는 안 되던가요? 제가 테스트할 때는 이렇게 그냥하니까 되고 encode 하니까 오히려 서버 쪽에서 글이 깨져 있더군요. post()가 알아서 인코드는 해 주는 듯 했는데요.

이 부분만 다시 답해주시면 저도 나중에 참고할 일이 있을지 모르니 부탁드립니다 ^^;

좋은 하루 되세요!

ipes4579의 이미지

저는 encode('UTF-8', "안녕하세요")를 "안녕하세요" 로 바꿔 보내니 안됩니다.
동일한 에러메시지가 나오네요. 미묘한 모듈 버전의 차이 때문일까요?
혹은 위 링크를 참고해보니 파일 인코딩 문제일 수도 있을 것 같기도 하고.. 아아 한글 어렵네요.

raymundo의 이미지

정말 묘하군요ㅋ

나중에라도 혹시 필요할지 몰라서, 제가 썼던 테스트 코드를 올려 둡니다.

서버쪽 form.cgi

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
 
my $q = CGI->new;
# $q->charset('UTF-8');
print $q->header("text/plain");
print $q->param('textarea1');
 
# out 파일에는 textarea1 필드의 값만 저장
open my $fh,'>', 'out.txt';
print {$fh} $q->param('textarea1');
 
# log 파일에 넘겨받은 파라메터 목록을 저장하게 했음
open my $fh2,'>', 'log.txt';
my %params = $q->Vars;
foreach my $k ( sort keys %params ) {
    print {$fh2} "[$k][$params{$k}]\n";
}

윈도우PC 쪽의 post.pl

#!perl
use strict;
use warnings;
use utf8;
use Encode;
 
use WWW::Mechanize;
 
my $browser = WWW::Mechanize->new();
my $url = 'http://gypark.pe.kr/cgi-bin/z/form.cgi';
 
$browser->post($url,
                [
                    textarea1 => "가각간",
#                    textarea1 => encode("UTF-8","가각간"), # 인코드 할지 말지
                    details => "hhh",
                ],
#                 Content_Type => 'form_data',      # 이걸 붙일지 말지
            );

결과:

1) 인코드 안 하고, content_type 지정하는 라인 주석처리

::::::::::::::
out.txt
::::::::::::::
가각간
::::::::::::::
log.txt
::::::::::::::
[details][hhh]
[textarea1][가각간]

2) 인코드 안 하고, content_type 라인 추가

::::::::::::::
out.txt
::::::::::::::
::::::::::::::
log.txt
::::::::::::::
[POSTDATA][textarea1=%EA%B0%80%EA%B0%81%EA%B0%84&details=hhh]

3) 인코드 하고, content_type 지정하는 라인 주석처리

::::::::::::::
out.txt
::::::::::::::
���
::::::::::::::
log.txt
::::::::::::::
[details][hhh]
[textarea1][���]

보다시피 한글이 인코드를 하면 오히려 받는 쪽에서 보면 깨져 있네요

4) 인코드 하고, content_type 라인 추가

::::::::::::::
out.txt
::::::::::::::
::::::::::::::
log.txt
::::::::::::::
[POSTDATA][textarea1=%C3%AA%C2%B0%C2%80%C3%AA%C2%B0%C2%81%C3%AA%C2%B0%C2%84&deta
ils=hhh]

인코드를 하면 "가각간"이 "%C3%AA%C2%B0%C2%80%C3%AA%C2%B0%C2%81%C3%AA%C2%B0%C2%84"가 되어 있는데, 이건 "가각간"을 UTF-8로 인코드한 "%EA%B0%80%EA%B0%81%EA%B0%84"를 한번 더 UTF_8로 인코드한 결과입니다. 즉 이중으로 인코딩해버린거죠.

그래서 저는 그냥 디코드된 상태의 "안녕하세요"를 post()에 인자로 넣으면 post에서 알아서 바꿔준다고 생각했는데 ipes4579님의 경우는 그 반대로, 인코드를 해서 post()에 넣어야 하고, 하지 않을 경우 에러가 나는 상황이군요.

저는 POST 나 CGI 이런 거 잘 몰라서... 제 post.pl 또는 form.cgi 코드 쪽에 뭔가 ipes4579님과 다르게 동작할 원인이 있는 건지는 잘 모르겠네요. 암튼 일단 상황 정리는 되었고 나머지는 지나가던 고수님이 봐주시길 바랄 수 밖에~

좋은 하루 되세요!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.